package com.my.swas.common.utils.ehcache;

import org.apache.commons.lang3.StringUtils;
import org.ehcache.Cache;
import org.ehcache.CacheManager;
import org.ehcache.config.CacheConfiguration;
import org.ehcache.config.builders.CacheConfigurationBuilder;
import org.ehcache.config.builders.CacheManagerBuilder;
import org.ehcache.config.builders.ResourcePoolsBuilder;
import org.ehcache.config.units.EntryUnit;
import org.ehcache.config.units.MemoryUnit;
import org.ehcache.expiry.ExpiryPolicy;
import org.springframework.context.annotation.Configuration;

import java.util.concurrent.locks.ReentrantLock;


/**
 * @Description:
 * @author: :MaYong
 * @Date: 2018/9/15 11:02
 */

@Configuration
public class EhcacheUtils {

    // 并发访问锁
    private static final ReentrantLock lock = new ReentrantLock();
    private static CacheManager cacheManager;

    private static String DEFAULT_CACHE = "defaultCache";

    //该出值由SSOProperties.java中的bean方法注入
    private static String rootDir;

    private static void init() {
        lock.lock();
        try {
            if (cacheManager == null) {
                System.out.println("[Ehcache配置初始化<开始>]");
                // CacheManager管理缓存
                String rootDir = getRootDir();
                cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
                        // 硬盘持久化地址
                        .with(CacheManagerBuilder.persistence(StringUtils.isNotEmpty(rootDir) ? rootDir : "D:/ehcacheData"))
                        // 设置一个默认缓存配置
                        .withCache(DEFAULT_CACHE, initDefaultCache())
                        //.withCache(DEFAULT_CACHE, initDefaultCache()) 如果有多个缓存配置可以配置多个
                        //创建之后立即初始化
                        .build(true);
                System.out.println("[Ehcache配置初始化<完成>]");
            }
        } finally {
            lock.unlock();
        }
    }

    /**
     * @author MaYong
     */
    private static <K, V> void init(String cacheName, CacheConfiguration<K, V> cacheConfiguration) {
        lock.lock();
        try {
            if (cacheManager == null) {
                System.out.println("[Ehcache配置初始化<开始>]");
                // 配置默认缓存属性
                // CacheManager管理缓存
                String rootDir = getRootDir();
                cacheManager = CacheManagerBuilder.newCacheManagerBuilder()
                        // 硬盘持久化地址
                        .with(CacheManagerBuilder.persistence(StringUtils.isNotEmpty(rootDir) ? rootDir : "D:/ehcacheData"))
                        // 设置一个默认缓存配置
                        .withCache(cacheName, cacheConfiguration)
                        //.withCache(DEFAULT_CACHE, initDefaultCache()) 如果有多个缓存配置可以配置多个
                        //创建之后立即初始化
                        .build(true);
                System.out.println("[Ehcache配置初始化<完成>]");
            }
        } finally {
            lock.unlock();
        }
    }


    /**
     * 配置默认缓存位置
     *
     * @return
     */
    private static CacheConfiguration<String, String> initDefaultCache() {
        CacheConfiguration<String, String> cacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(
                // 缓存数据K和V的数值类型
                // 在ehcache3.3以后中必须指定缓存键值类型,如果使用中类型与配置的不同,会报类转换异常
                String.class, String.class,
                ResourcePoolsBuilder
                        .newResourcePoolsBuilder()
                        //设置缓存堆容纳元素个数(JVM内存空间)超出个数后会存到offheap中
                        .heap(1000L, EntryUnit.ENTRIES)
                        //设置堆外储存大小(内存存储) 超出offheap的大小会被淘汰规则被淘汰
                        .offheap(100L, MemoryUnit.MB)
                        // 配置磁盘持久化储存(硬盘存储)用来持久化到磁盘,这里设置为false不启用
                        .disk(500L, MemoryUnit.MB, false)
        ).withExpiry(ExpiryPolicy.NO_EXPIRY).build();
        return cacheConfiguration;
    }


    /**
     * 可以注入属于自己自定义cache
     *
     * @return 配置文件实例
     */
    public static <K, V> CacheManager getInstance(String cacheName, CacheConfiguration<K, V> cacheConfiguration) {
        if (cacheManager == null) {
            init(cacheName, cacheConfiguration);
        }
        return cacheManager;
    }

    /**
     * 默认配置
     *
     * @return 配置文件实例
     */
    public static <K, V> CacheManager getInstance() {
        if (cacheManager == null) {
            init();
        }
        return cacheManager;
    }


    public static Cache<String, String> getDefaultEhcache() {
        Cache<String, String> mineCache = getInstance().getCache(DEFAULT_CACHE, String.class, String.class);
        return mineCache;
    }

    public static String getRootDir() {
        return rootDir;
    }

    public static void setRootDir(String rootDir) {
        EhcacheUtils.rootDir = rootDir;
    }
}
